package cn.itqiqi.student_system_java.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.regex.Pattern;

/**
 * 时间工具类
 * 
 *
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";


    public static String YYYYMMDD = "yyyy年MM月dd日";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    private static final long ONE_MINUTE = 60000L;
    private static final long ONE_HOUR = 3600000L;
    private static final long ONE_DAY = 86400000L;
    private static final long ONE_WEEK = 604800000L;

    private static final String ONE_SECOND_AGO = "秒前";
    private static final String ONE_MINUTE_AGO = "分钟前";
    private static final String ONE_HOUR_AGO = "小时前";
    private static final String ONE_DAY_AGO = "天前";
    private static final String ONE_MONTH_AGO = "月前";
    private static final String ONE_YEAR_AGO = "年前";

    /**
     * 几小时前，几天前....
     *
     * @param dateTime
     * @return
     */
    public static String timeCount(Date dateTime) {
        String format = format(dateTime);
        return format;
    }

    /**
     * 时间转换
     */
    public static String format(Date date) {
        long delta = System.currentTimeMillis() - date.getTime();
        if (delta < 1L * ONE_MINUTE) {
            long seconds = toSeconds(delta);
            return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO;
        }
        if (delta < 45L * ONE_MINUTE) {
            long minutes = toMinutes(delta);
            return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO;
        }
        if (delta < 24L * ONE_HOUR) {
            long hours = toHours(delta);
            return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO;
        }
        if (delta < 48L * ONE_HOUR) {
            return "昨天";
        }
        if (delta < 30L * ONE_DAY) {
            long days = toDays(delta);
            return (days <= 0 ? 1 : days) + ONE_DAY_AGO;
        }
        if (delta < 12L * 4L * ONE_WEEK) {
            long months = toMonths(delta);
            return (months <= 0 ? 1 : months) + ONE_MONTH_AGO;
        } else {
            long years = toYears(delta);
            return (years <= 0 ? 1 : years) + ONE_YEAR_AGO;
        }
    }

    private static long toSeconds(long date) {
        return date / 1000L;
    }

    private static long toMinutes(long date) {
        return toSeconds(date) / 60L;
    }

    private static long toHours(long date) {
        return toMinutes(date) / 60L;
    }

    private static long toDays(long date) {
        return toHours(date) / 24L;
    }

    private static long toMonths(long date) {
        return toDays(date) / 30L;
    }

    private static long toYears(long date) {
        return toMonths(date) / 365L;
    }


    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    
    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }


    /**
     * 获取系统当前时间（yyyyMMdd）
     */
    public static String getSystemDate( String format){
        String formatDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(format));
        return  formatDateTime;
    }

    /**
     * date日期转换成String
     * @param date 待转换的date类型的日期
     * @param pattern 日期格式 如：yyyyMMdd、yyyy年MM月dd日
     * @return String类型的日期
     */
    public static String getDateToString(Date date,String pattern){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return  simpleDateFormat.format(date);
    }

    /**
     * 处理 excel中 [h]:mm:ss 时间格式数据
     * @param endDate 待处理的时间
     * @return  HH:mm:ss
     */
    public static String handleToHMMSS(Date endDate) {
        GregorianCalendar gregorianCalendar = new GregorianCalendar(1900, 0, 0);
        gregorianCalendar.add(Calendar.YEAR, 1000);
        Date startdate = gregorianCalendar.getTime();

        Calendar instance = Calendar.getInstance();
        instance.setTime(endDate);
        instance.add(Calendar.YEAR, 1000);
        endDate = instance.getTime();

        long diff = endDate.getTime() - startdate.getTime();
        diff = diff < 0 ? -diff : diff;
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 计算差多少小时
        long hour = diff / nh;
        // 计算差多少分
        long min = diff % nd % nh / nm;
        // 计算差多少秒
        long sec = diff % nd % nh % nm / ns;
        return hour + ":" + min + ":" + sec;
    }

    /**
     * [h]:mm:ss 格式时间转换成时间戳
     * @param timeStr
     * @return 时间戳
     */
    public static Long handleHMMSSToLong(String timeStr){
        if (timeStr == null) {
            return 0L;
        }
        String[] split = timeStr.split(":");
        return new Long(split[0]) * 60 * 60 * 1000 + new Long(split[1]) * 60 * 1000 + new Long(split[2]) * 1000;
    }

    /**
     * 时间戳转换成 [h]:mm:ss 格式
     * @param time
     * @return
     */
    public static String handleLongToHMMSS(Long time) {
        if (time == 0L) {
            return "0:0:0";
        }
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 计算差多少小时
        long hour = time / nh;
        // 计算差多少分
        long min = time % nd % nh / nm;
        // 计算差多少秒
        long sec = time % nd % nh % nm / ns;
        return hour + ":" + min + ":" + sec;
    }

    /**
     * 时间校验（校验客户输入的格式  是不是：[h]:mm:ss）
     * 如果成功则返回null，如果失败则返回失败原因。
     */
    public static String verifyTime(String time){
        String[] timeSplit = time.split(":");
        if(timeSplit.length != 3){
            return "错误的时间格式(请阅读校验规则)";
        }else{
            for (String s : timeSplit) {
                if(!isNum(s)){
                    return "错误的时间格式(请阅读校验规则)";
                }
            }
            if(Long.parseLong(timeSplit[1]) > 59){
                return "分钟不能设置大于60";
            }
            if(Long.parseLong(timeSplit[2]) > 59){
                return "秒不能设置大于60";
            }
        }
        return null;
    }

    /**
     * 校验是否是纯数字
     * @param str
     * @return
     */
    public static boolean isNum(String str){
        @SuppressWarnings("AlibabaAvoidPatternCompileInMethod") Pattern pattern = Pattern.compile("^-?[0-9]+");
        if(pattern.matcher(str).matches()){
            //数字
            return true;
        } else {
            //非数字
            return false;
        }
    }

    // 时间戳转字符串  1503991612952 ==> 2017-08-29 15:26:52  时间戳 是long 类型
    public static String timeToString(String s){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = sdf.parse(sdf.format(new Date(new Long(s))));
            //Date date = sdf.parse(sdf.format(new Long(s)));// 等价于
            return sdf.format(date);
        } catch (NumberFormatException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (ParseException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return null;
    }


    // 字符串转时间戳 2017-08-29 15:26:52 ==> 1503991612952
    public static String stringToTime(String s){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = sdf.parse(s);
            return String.valueOf(date.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取当前日期前后日期 返回yyyy-MM-dd
     * @param amount 相差天数
     * @return
     */
    public static String getNearDayDate(int amount) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        Date date = new Date();
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.DAY_OF_MONTH,amount);
       return sdf.format(now.getTime());
    }

    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @return 相差天数
     * @Author: YaHuiLi
     * @Date: Create in 2021/10/22/12:15
     */
    public static int daysBetween(Date smdate,Date bdate) {
        SimpleDateFormat formatter  = new SimpleDateFormat(YYYY_MM_DD);
        String format = formatter.format(smdate);
        String format2 = formatter.format(bdate);
        smdate = java.sql.Date.valueOf(format);
        bdate = java.sql.Date.valueOf(format2);

        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 日期加或减num天
     *
     * @param sDate 当前时期
     * @param num 日期加或减num天
     * @return
     */
    public static Date getDateByDay(Date sDate, int num) {
        Calendar cal = Calendar.getInstance();
        // 设置开始时间
        cal.setTime(sDate);
        //增加或减少num天
        cal.add(Calendar.DATE, num);
        return cal.getTime();
    }

    /**
     * 去除时间时分秒 YYYY_MM_DD 用来判断一天内的公告
     *
     * @param date
     * @return
     */
    public static Date dateToYearMonthDay(Date date)
    {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date);
        // 将时分秒,毫秒域清零
        cal1.set(Calendar.HOUR_OF_DAY, 0);
        cal1.set(Calendar.MINUTE, 0);
        cal1.set(Calendar.SECOND, 0);
        cal1.set(Calendar.MILLISECOND, 0);
        return cal1.getTime();
    }
   /**
    * @Description: 根据日期字符串获取Date
    * @Param: [strDate, pattern]日期字符串，格式
    * @Return: java.util.Date
    **/
    public static Date strToDate(String strDate,String pattern) {
          SimpleDateFormat formatter = new SimpleDateFormat(pattern);
          ParsePosition pos = new ParsePosition(0);
          Date strtodate = formatter.parse(strDate, pos);
          return strtodate;
    }
    /**
     * @Description:获取两个日期的时间差 精确到秒
     * @Param: [bigDate, smallDate]
     * @Return: java.lang.String
     **/
    public static String timeDiff(Date bigDate,Date smallDate) {
        long between = bigDate.getTime() - smallDate.getTime();
        long day = between / (24 * 60 * 60 * 1000);
        long hour = (between / (60 * 60 * 1000) - day * 24);
        long min = ((between / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (between / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        return day + "d" + hour + "h" + min + "min" + s + "s";
    }
}
